//定义设备基类Thing、属性、方法、参数等核心数据结构
#ifndef THING_H
#define THING_H

#include <string>
#include <map>
#include <functional>
#include <vector>
#include <stdexcept>
#include <cJSON.h>

namespace iot {

// 定义属性值类型的枚举，支持布尔型、数值型和字符串型
enum ValueType {
    kValueTypeBoolean,  // 布尔类型
    kValueTypeNumber,   // 数值类型
    kValueTypeString    // 字符串类型
};

// 属性类：表示设备的只读状态属性
class Property {
private:
    std::string name_;                    // 属性名称
    std::string description_;             // 属性描述
    ValueType type_;                      // 属性值类型
    
    // 不同类型的getter函数，用于获取属性值
    std::function<bool()> boolean_getter_;      // 布尔型属性获取函数
    std::function<int()> number_getter_;        // 数值型属性获取函数
    std::function<std::string()> string_getter_; // 字符串型属性获取函数

public:
    // 构造函数：针对布尔型属性
    Property(const std::string& name, const std::string& description, std::function<bool()> getter) :
        name_(name), description_(description), type_(kValueTypeBoolean), boolean_getter_(getter) {}
    
    // 构造函数：针对数值型属性
    Property(const std::string& name, const std::string& description, std::function<int()> getter) :
        name_(name), description_(description), type_(kValueTypeNumber), number_getter_(getter) {}
    
    // 构造函数：针对字符串型属性
    Property(const std::string& name, const std::string& description, std::function<std::string()> getter) :
        name_(name), description_(description), type_(kValueTypeString), string_getter_(getter) {}

    // 获取属性名称
    const std::string& name() const { return name_; }
    
    // 获取属性描述
    const std::string& description() const { return description_; }
    
    // 获取属性类型
    ValueType type() const { return type_; }

    // 获取布尔型属性值
    bool boolean() const { return boolean_getter_(); }
    
    // 获取数值型属性值
    int number() const { return number_getter_(); }
    
    // 获取字符串型属性值
    std::string string() const { return string_getter_(); }

    // 生成属性描述的JSON格式字符串
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        if (type_ == kValueTypeBoolean) {
            json_str += "\"type\":\"boolean\"";
        } else if (type_ == kValueTypeNumber) {
            json_str += "\"type\":\"number\"";
        } else if (type_ == kValueTypeString) {
            json_str += "\"type\":\"string\"";
        }
        json_str += "}";
        return json_str;
    }

    // 生成属性当前状态值的JSON格式字符串
    std::string GetStateJson() {
        if (type_ == kValueTypeBoolean) {
            return boolean_getter_() ? "true" : "false";
        } else if (type_ == kValueTypeNumber) {
            return std::to_string(number_getter_());
        } else if (type_ == kValueTypeString) {
            return "\"" + string_getter_() + "\"";
        }
        return "null";
    }
};

// 属性列表类：管理多个属性的集合
class PropertyList {
private:
    std::vector<Property> properties_;  // 属性容器

public:
    // 默认构造函数
    PropertyList() = default;
    
    // 使用属性向量构造
    PropertyList(const std::vector<Property>& properties) : properties_(properties) {}

    // 添加布尔型属性
    void AddBooleanProperty(const std::string& name, const std::string& description, std::function<bool()> getter) {
        properties_.push_back(Property(name, description, getter));
    }
    
    // 添加数值型属性
    void AddNumberProperty(const std::string& name, const std::string& description, std::function<int()> getter) {
        properties_.push_back(Property(name, description, getter));
    }
    
    // 添加字符串型属性
    void AddStringProperty(const std::string& name, const std::string& description, std::function<std::string()> getter) {
        properties_.push_back(Property(name, description, getter));
    }

    // 通过名称查找属性（const版本）
    const Property& operator[](const std::string& name) const {
        for (auto& property : properties_) {
            if (property.name() == name) {
                return property;
            }
        }
        throw std::runtime_error("Property not found: " + name);
    }

    // 生成所有属性描述的JSON格式字符串
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& property : properties_) {
            json_str += "\"" + property.name() + "\":" + property.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }

    // 生成所有属性当前状态的JSON格式字符串
    std::string GetStateJson() {
        std::string json_str = "{";
        for (auto& property : properties_) {
            json_str += "\"" + property.name() + "\":" + property.GetStateJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

// 参数类：表示方法调用时的输入参数
class Parameter {
private:
    std::string name_;          // 参数名称
    std::string description_;   // 参数描述
    ValueType type_;            // 参数类型
    bool required_;             // 是否必需参数
    
    // 参数值存储
    bool boolean_;              // 布尔型参数值
    int number_;                // 数值型参数值
    std::string string_;        // 字符串型参数值

public:
    // 构造函数：创建参数定义
    Parameter(const std::string& name, const std::string& description, ValueType type, bool required = true) :
        name_(name), description_(description), type_(type), required_(required) {}

    // 获取参数名称
    const std::string& name() const { return name_; }
    
    // 获取参数描述
    const std::string& description() const { return description_; }
    
    // 获取参数类型
    ValueType type() const { return type_; }
    
    // 判断是否为必需参数
    bool required() const { return required_; }

    // 获取参数值（不同类型）
    bool boolean() const { return boolean_; }
    int number() const { return number_; }
    const std::string& string() const { return string_; }

    // 设置参数值（不同类型）
    void set_boolean(bool value) { boolean_ = value; }
    void set_number(int value) { number_ = value; }
    void set_string(const std::string& value) { string_ = value; }

    // 生成参数描述的JSON格式字符串
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        if (type_ == kValueTypeBoolean) {
            json_str += "\"type\":\"boolean\"";
        } else if (type_ == kValueTypeNumber) {
            json_str += "\"type\":\"number\"";
        } else if (type_ == kValueTypeString) {
            json_str += "\"type\":\"string\"";
        }
        json_str += "}";
        return json_str;
    }
};

// 参数列表类：管理多个参数的集合
class ParameterList {
private:
    std::vector<Parameter> parameters_;  // 参数容器

public:
    // 默认构造函数
    ParameterList() = default;
    
    // 使用参数向量构造
    ParameterList(const std::vector<Parameter>& parameters) : parameters_(parameters) {}
    
    // 添加参数
    void AddParameter(const Parameter& parameter) {
        parameters_.push_back(parameter);
    }

    // 通过名称查找参数（const版本）
    const Parameter& operator[](const std::string& name) const {
        for (auto& parameter : parameters_) {
            if (parameter.name() == name) {
                return parameter;
            }
        }
        throw std::runtime_error("Parameter not found: " + name);
    }

    // 迭代器支持
    auto begin() { return parameters_.begin(); }
    auto end() { return parameters_.end(); }

    // 生成所有参数描述的JSON格式字符串
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& parameter : parameters_) {
            json_str += "\"" + parameter.name() + "\":" + parameter.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

// 方法类：表示设备可执行的操作
class Method {
private:
    std::string name_;                          // 方法名称
    std::string description_;                   // 方法描述
    ParameterList parameters_;                   // 方法参数列表
    std::function<void(const ParameterList&)> callback_;  // 方法执行回调函数

public:
    // 构造函数：创建方法定义
    Method(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) :
        name_(name), description_(description), parameters_(parameters), callback_(callback) {}

    // 获取方法名称
    const std::string& name() const { return name_; }
    
    // 获取方法描述
    const std::string& description() const { return description_; }
    
    // 获取方法参数列表
    ParameterList& parameters() { return parameters_; }

    // 生成方法描述的JSON格式字符串
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        json_str += "\"parameters\":" + parameters_.GetDescriptorJson();
        json_str += "}";
        return json_str;
    }

    // 执行方法
    void Invoke() {
        callback_(parameters_);
    }
};

// 方法列表类：管理多个方法的集合
class MethodList {
private:
    std::vector<Method> methods_;  // 方法容器

public:
    // 默认构造函数
    MethodList() = default;
    
    // 使用方法向量构造
    MethodList(const std::vector<Method>& methods) : methods_(methods) {}

    // 添加方法
    void AddMethod(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) {
        methods_.push_back(Method(name, description, parameters, callback));
    }

    // 通过名称查找方法
    Method& operator[](const std::string& name) {
        for (auto& method : methods_) {
            if (method.name() == name) {
                return method;
            }
        }
        throw std::runtime_error("Method not found: " + name);
    }

    // 生成所有方法描述的JSON格式字符串
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& method : methods_) {
            json_str += "\"" + method.name() + "\":" + method.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

// 设备基类：表示一个物联网设备
class Thing {
public:
    // 构造函数：创建设备实例
    Thing(const std::string& name, const std::string& description) :
        name_(name), description_(description) {}
    
    // 虚析构函数
    virtual ~Thing() = default;

    // 纯虚函数：获取设备描述的JSON格式字符串
    virtual std::string GetDescriptorJson();
    
    // 纯虚函数：获取设备状态的JSON格式字符串
    virtual std::string GetStateJson();
    
    // 纯虚函数：执行设备命令
    virtual void Invoke(const cJSON* command);

    // 获取设备名称
    const std::string& name() const { return name_; }
    
    // 获取设备描述
    const std::string& description() const { return description_; }

protected:
    PropertyList properties_;  // 设备属性列表
    MethodList methods_;       // 设备方法列表

private:
    std::string name_;         // 设备名称
    std::string description_;  // 设备描述
};

// 注册设备类型的函数声明
void RegisterThing(const std::string& type, std::function<Thing*()> creator);

// 创建设备实例的函数声明
Thing* CreateThing(const std::string& type);

// 宏定义：用于声明和注册设备类型
#define DECLARE_THING(TypeName) \
    static iot::Thing* Create##TypeName() { \
        return new iot::TypeName(); \
    } \
    static bool Register##TypeNameHelper = []() { \
        RegisterThing(#TypeName, Create##TypeName); \
        return true; \
    }();

} // namespace iot

#endif // THING_H
#ifndef THING_H
#define THING_H

#include <string>
#include <map>
#include <functional>
#include <vector>
#include <stdexcept>
#include <cJSON.h>

namespace iot {

enum ValueType {
    kValueTypeBoolean,
    kValueTypeNumber,
    kValueTypeString
};

class Property {
private:
    std::string name_;
    std::string description_;
    ValueType type_;
    std::function<bool()> boolean_getter_;
    std::function<int()> number_getter_;
    std::function<std::string()> string_getter_;

public:
    Property(const std::string& name, const std::string& description, std::function<bool()> getter) :
        name_(name), description_(description), type_(kValueTypeBoolean), boolean_getter_(getter) {}
    Property(const std::string& name, const std::string& description, std::function<int()> getter) :
        name_(name), description_(description), type_(kValueTypeNumber), number_getter_(getter) {}
    Property(const std::string& name, const std::string& description, std::function<std::string()> getter) :
        name_(name), description_(description), type_(kValueTypeString), string_getter_(getter) {}

    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }
    ValueType type() const { return type_; }

    bool boolean() const { return boolean_getter_(); }
    int number() const { return number_getter_(); }
    std::string string() const { return string_getter_(); }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        if (type_ == kValueTypeBoolean) {
            json_str += "\"type\":\"boolean\"";
        } else if (type_ == kValueTypeNumber) {
            json_str += "\"type\":\"number\"";
        } else if (type_ == kValueTypeString) {
            json_str += "\"type\":\"string\"";
        }
        json_str += "}";
        return json_str;
    }

    std::string GetStateJson() {
        if (type_ == kValueTypeBoolean) {
            return boolean_getter_() ? "true" : "false";
        } else if (type_ == kValueTypeNumber) {
            return std::to_string(number_getter_());
        } else if (type_ == kValueTypeString) {
            return "\"" + string_getter_() + "\"";
        }
        return "null";
    }
};

class PropertyList {
private:
    std::vector<Property> properties_;

public:
    PropertyList() = default;
    PropertyList(const std::vector<Property>& properties) : properties_(properties) {}

    void AddBooleanProperty(const std::string& name, const std::string& description, std::function<bool()> getter) {
        properties_.push_back(Property(name, description, getter));
    }
    void AddNumberProperty(const std::string& name, const std::string& description, std::function<int()> getter) {
        properties_.push_back(Property(name, description, getter));
    }
    void AddStringProperty(const std::string& name, const std::string& description, std::function<std::string()> getter) {
        properties_.push_back(Property(name, description, getter));
    }

    const Property& operator[](const std::string& name) const {
        for (auto& property : properties_) {
            if (property.name() == name) {
                return property;
            }
        }
        throw std::runtime_error("Property not found: " + name);
    }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& property : properties_) {
            json_str += "\"" + property.name() + "\":" + property.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }

    std::string GetStateJson() {
        std::string json_str = "{";
        for (auto& property : properties_) {
            json_str += "\"" + property.name() + "\":" + property.GetStateJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

class Parameter {
private:
    std::string name_;
    std::string description_;
    ValueType type_;
    bool required_;
    bool boolean_;
    int number_;
    std::string string_;

public:
    Parameter(const std::string& name, const std::string& description, ValueType type, bool required = true) :
        name_(name), description_(description), type_(type), required_(required) {}

    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }
    ValueType type() const { return type_; }
    bool required() const { return required_; }

    bool boolean() const { return boolean_; }
    int number() const { return number_; }
    const std::string& string() const { return string_; }

    void set_boolean(bool value) { boolean_ = value; }
    void set_number(int value) { number_ = value; }
    void set_string(const std::string& value) { string_ = value; }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        if (type_ == kValueTypeBoolean) {
            json_str += "\"type\":\"boolean\"";
        } else if (type_ == kValueTypeNumber) {
            json_str += "\"type\":\"number\"";
        } else if (type_ == kValueTypeString) {
            json_str += "\"type\":\"string\"";
        }
        json_str += "}";
        return json_str;
    }
};

class ParameterList {
private:
    std::vector<Parameter> parameters_;

public:
    ParameterList() = default;
    ParameterList(const std::vector<Parameter>& parameters) : parameters_(parameters) {}
    void AddParameter(const Parameter& parameter) {
        parameters_.push_back(parameter);
    }

    const Parameter& operator[](const std::string& name) const {
        for (auto& parameter : parameters_) {
            if (parameter.name() == name) {
                return parameter;
            }
        }
        throw std::runtime_error("Parameter not found: " + name);
    }

    // iterator
    auto begin() { return parameters_.begin(); }
    auto end() { return parameters_.end(); }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& parameter : parameters_) {
            json_str += "\"" + parameter.name() + "\":" + parameter.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

class Method {
private:
    std::string name_;
    std::string description_;
    ParameterList parameters_;
    std::function<void(const ParameterList&)> callback_;

public:
    Method(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) :
        name_(name), description_(description), parameters_(parameters), callback_(callback) {}

    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }
    ParameterList& parameters() { return parameters_; }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        json_str += "\"parameters\":" + parameters_.GetDescriptorJson();
        json_str += "}";
        return json_str;
    }

    void Invoke() {
        callback_(parameters_);
    }
};

class MethodList {
private:
    std::vector<Method> methods_;

public:
    MethodList() = default;
    MethodList(const std::vector<Method>& methods) : methods_(methods) {}

    void AddMethod(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) {
        methods_.push_back(Method(name, description, parameters, callback));
    }

    Method& operator[](const std::string& name) {
        for (auto& method : methods_) {
            if (method.name() == name) {
                return method;
            }
        }
        throw std::runtime_error("Method not found: " + name);
    }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& method : methods_) {
            json_str += "\"" + method.name() + "\":" + method.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

class Thing {
public:
    Thing(const std::string& name, const std::string& description) :
        name_(name), description_(description) {}
    virtual ~Thing() = default;

    virtual std::string GetDescriptorJson();
    virtual std::string GetStateJson();
    virtual void Invoke(const cJSON* command);

    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }

protected:
    PropertyList properties_;
    MethodList methods_;

private:
    std::string name_;
    std::string description_;
};


void RegisterThing(const std::string& type, std::function<Thing*()> creator);
Thing* CreateThing(const std::string& type);

#define DECLARE_THING(TypeName) \
    static iot::Thing* Create##TypeName() { \
        return new iot::TypeName(); \
    } \
    static bool Register##TypeNameHelper = []() { \
        RegisterThing(#TypeName, Create##TypeName); \
        return true; \
    }();

} // namespace iot

#endif // THING_H
